<template>
  <div class="blog-toc-container">
    <h2>目录</h2>
    <RightList @select="handleSelect" :list="tocWithSelect" />
  </div>
</template>

<script>
import RightList from './RightList.vue';
import { debounce } from '@/utils';
export default {
  components: {
    RightList,
  },
  props: {
    toc: {
      type: Array,
      required: true,
    }
  },
  data() {
    return {
      activeAnchor: "",
    }
  },
  created() {
    this.enforceSetSelect = debounce(this.setSelect, 50);
    this.$bus.$on("mainScroll", this.enforceSetSelect);
  },
  destroyed(){
    this.$bus.$off("mainScroll",this.enforceSetSelect);
  },
  methods: {
    handleSelect(item) {
      location.hash = item.anchor;
    },
    // 设置activeAnchor为正确的值
    setSelect(scrollDom) {
      if(!scrollDom){
        return;
      }
      this.activeAnchor = ""; // 先清空之前的状态
      const range = 200;
      for (const dom of this.doms) {
        if (!dom) {
          continue;
        }
        const top = dom.getBoundingClientRect().top;
        if (top >= 0 && top <= range) {
          // 在规定的范围内
          this.activeAnchor = dom.id;
          return;
        } else if (top > range) {
          // 在规定范围的下方
          return;
        } else {
          // 在规定范围的上方
          this.activeAnchor = dom.id;
        }
      }
    },
  },
  computed: {
    // 根据toc属性和anchor得到带有isselect属性的toc数组
    tocWithSelect() {
      const getTOC = (toc = []) => {
        return toc.map(t => ({
          ...t, // 将所有属性展开到数组
          isSelect: t.anchor === this.activeAnchor, // 添加一个选中属性
          children: getTOC(t.children), // 递归子数组（页面中的子目录）
        }));
      };
      return getTOC(this.toc);
    },
    // 根据toc得到对应元素数组
    doms() {
      const doms = [];
      const addToDoms = toc => {
        for (const t of toc) {
          doms.push(document.getElementById(t.anchor));
          if (t.children && t.children.length) {
            addToDoms(t.children);
          }
        }
      };
      addToDoms(this.toc);
      return doms;
    },
  },
}
</script>

<style lang="less" scoped>
.blog-toc-container {
  width: 100%;
  box-sizing: border-box;
  padding: 20px;

  h2 {
    font-weight: bold;
    letter-spacing: 2px;
    font-size: 1em;
    margin: 0;
  }
}
</style>